package com.wang.jmonkey.ca.filter;

import cn.hutool.core.util.StrUtil;
import com.wang.jmonkey.ca.exception.AuthParamException;
import com.wang.jmonkey.ca.exception.ValidateCodeException;
import com.wang.jmonkey.ca.handler.code.ValidateCodeHandlerHolder;
import com.wang.jmonkey.ca.model.AuthParam;
import com.wang.jmonkey.ca.property.SecurityProperty;
import com.wang.jmonkey.common.constant.SecurityConstant;
import com.wang.jmonkey.common.constant.ValidateConstant;
import org.springframework.boot.web.context.ConfigurableWebServerApplicationContext;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @Description 普通登陆拦截器
 * @Author HeJiawang
 * @Date 2021/5/8 16:34
 */
@Component
public class GeneralAuthenticationFilter extends AbstractAuthenticationFilter {

    private ConfigurableWebServerApplicationContext context;

    public GeneralAuthenticationFilter(SecurityProperty securityProperty , AuthenticationManager authenticationManager , ConfigurableWebServerApplicationContext context) {
        super(
                new AntPathRequestMatcher(
                        getLoginUrl(securityProperty , GeneralAuthenticationFilter.class),
                        getMethod(securityProperty , GeneralAuthenticationFilter.class)
                ),
                authenticationManager
        );

        this.context = context;
    }

    @Override
    protected Authentication authentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException, ServletException {

        AuthParam auth = new AuthParam(request , context);
        validateAuthParam(auth, request);

        UsernamePasswordAuthenticationToken authRequestToken =
                new UsernamePasswordAuthenticationToken(auth.getUsername() , auth.getPassword());
        return this.getAuthenticationManager().authenticate(authRequestToken);
    }

    /**
     * 校验接口必填桉树
     * @param auth param
     */
    private void validateAuthParam(AuthParam auth, HttpServletRequest request) {
        if (StrUtil.equalsAnyIgnoreCase(auth.getOauthType(), SecurityConstant.OAuthType.access_token.getKey())) {
            // 校验生成token请求的必填参数

            if (StrUtil.isEmpty(auth.getUsername())) {
                throw new AuthParamException("请输入登陆名称");
            }

            if (StrUtil.isEmpty(auth.getPassword())) {
                throw new AuthParamException("请输入登陆面膜");
            }

            if (StrUtil.isEmpty(auth.getDeviceId())) {
                throw new AuthParamException("请输入DeviceId");
            }

            if (StrUtil.isEmpty(auth.getCode())) {
                throw new AuthParamException("请输入验证码");
            }

            ValidateCodeHandlerHolder validateCodeHandlerHolder = context.getBean(ValidateCodeHandlerHolder.class);
            if (!validateCodeHandlerHolder.findValidateCodeProcessor(ValidateConstant.ValidateCodeType.ImageValidateCodeHandler).validate(request)) {
                throw new ValidateCodeException("验证码不正确!");
            }
        }

        if (StrUtil.equalsAnyIgnoreCase(auth.getOauthType(), SecurityConstant.OAuthType.refresh_token.getKey())) {
            // 校验刷新token请求的必填参数

            if (StrUtil.isEmpty(auth.getRefreshToken())) {
                throw new AuthParamException("请输入RefreshToken");
            }
        }
    }
}
